package com.joysuch.wwyt.workflow.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.IdUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import com.joysuch.wwyt.bp.service.BpContractorStaffService;
import com.joysuch.wwyt.common.constant.Constant;
import com.joysuch.wwyt.config.RedisClient;
import com.joysuch.wwyt.core.bean.BaseAttachmentBean;
import com.joysuch.wwyt.core.bean.SimpleSelectListBean;
import com.joysuch.wwyt.core.common.ajax.ResultBean;
import com.joysuch.wwyt.core.common.util.PageDataUtils;
import com.joysuch.wwyt.core.common.util.SimpleDateFormatCache;
import com.joysuch.wwyt.core.constant.Constants;
import com.joysuch.wwyt.core.entity.BaseConfig;
import com.joysuch.wwyt.core.entity.BaseMenuFunction;
import com.joysuch.wwyt.core.enums.BaseConfigCodes;
import com.joysuch.wwyt.core.enums.Status;
import com.joysuch.wwyt.core.exception.ApiBusinessException;
import com.joysuch.wwyt.core.exception.ApiCoreException;
import com.joysuch.wwyt.core.repository.BaseMenuFunctionDao;
import com.joysuch.wwyt.core.service.BaseConfigService;
import com.joysuch.wwyt.core.service.BaseUserService;
import com.joysuch.wwyt.core.service.BizCodeGeneratorFacade;
import com.joysuch.wwyt.core.support.Context;
import com.joysuch.wwyt.mh.entity.MhMonitoringType;
import com.joysuch.wwyt.monitoringcenter.bean.ScreenColumnBean;
import com.joysuch.wwyt.util.PageableUtil;
import com.joysuch.wwyt.util.SpringBeanUtils;
import com.joysuch.wwyt.util.StringUtil;
import com.joysuch.wwyt.workflow.WorkFlowConstants;
import com.joysuch.wwyt.workflow.bean.*;
import com.joysuch.wwyt.workflow.engine.ProcessAPI;
import com.joysuch.wwyt.workflow.entity.*;
import com.joysuch.wwyt.workflow.entity.bo.ComponentStatisticBO;
import com.joysuch.wwyt.workflow.enums.ComponentCountEnum;
import com.joysuch.wwyt.workflow.enums.ModelDataSourceTypes;
import com.joysuch.wwyt.workflow.enums.WorkFlowFiledTypeEnum;
import com.joysuch.wwyt.workflow.enums.WorkFlowShowTypes;
import com.joysuch.wwyt.workflow.repository.*;
import com.joysuch.wwyt.workflow.service.WorkFlowProcessService;
import com.joysuch.wwyt.workflow.service.WorkFlowTaskProcessListService;
import javafx.util.Pair;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.Model;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.util.Assert;
import org.apache.shiro.util.CollectionUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.http.HttpEntity;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import javax.persistence.Tuple;
import java.io.IOException;
import java.math.BigInteger;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;


/**
 * @author qingzhou
 * 2020-02-12
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor = @__(@Autowired))
public class WorkFlowProcessServiceImpl implements WorkFlowProcessService {

    private final ProcessAPI processAPI;
    private final WorkFlowProcessDao workFlowProcessDao;
    @Autowired
    private WorkFlowMenuDao workFlowMenuDao;
    @Autowired
    private BaseMenuFunctionDao baseMenuFunctionDao;
    @Autowired
    private BaseUserService baseUserService;
    @Autowired
    private BpContractorStaffService bpContractorStaffService;
    @Autowired
    private WorkFlowLocationConfigDao locationConfigDao;
    @Autowired
    private WorkFlowScreenConfigDao screenConfigDao;
    @Autowired
    private WorkFlowTaskDao workFlowTaskDao;
    @Autowired
    private WorkFlowScreenTypeDao screenTypeDao;
    @Autowired
    private WorkFlowRailAlarmConfigDao alarmConfigDao;
    @Autowired
    private ScreenColumnConfigDao screenColumnConfigDao;
    @Autowired
    private BizCodeGeneratorFacade bizCodeGeneratorFacade;
    @Autowired
    private WorkFlowScreenConfigDao workFlowScreenConfigDao;
    @Autowired
    private WorkFlowProcessCodeStrategyDao workFlowProcessCodeStrategyDao;
    @Resource
    private RedisClient redisClient;
    @Autowired
    private WorkFlowTaskProcessListService workFlowTaskProcessListService;


    @Autowired
    private BaseConfigService baseConfigService;
    @Autowired
    private RestTemplate restTemplate;

    @Override
    public Optional<WorkFlowProcess> findById(Long processId) {
        return workFlowProcessDao.findById(processId);
    }

    @Override
    public String getModelId(Long processId) throws ApiBusinessException {
        WorkFlowEditModelBean modelBean = getProcessModel(processId);
        return modelBean.getModelId();
    }

    @Override
    public WorkFlowEditModelBean getProcessModel(Long processId) throws ApiBusinessException {

        Optional<WorkFlowProcess> optionalProcess = findById(processId);
        if (optionalProcess.isPresent()) {
            WorkFlowProcess process = optionalProcess.get();
            String modelId = process.getModelId();
            //代码复原 todo 后续优化：在创建流程的时候处理
            if (Strings.isNullOrEmpty(modelId)) {
                String modelKey = process.getBizName();
                Model model = processAPI.newModel(process.getBizName(), modelKey, process.getBizName());
                modelId = model.getId();
                process.setModelId(modelId);
                workFlowProcessDao.save(process);
            }
            WorkFlowEditModelBean modelBean = new WorkFlowEditModelBean();
            modelBean.setModelId(modelId);
            modelBean.setModelJson(process.getModelJson());
            return modelBean;
        } else {
            log.error("Find process error. process {} not exist", processId);
            throw new ApiBusinessException(Status.PROCESS_NOT_EXIST);
        }
    }

    @Override
    public Page<WorkFlowProcess> findByPage(Pageable pageable) {
        Page<WorkFlowProcess> page = workFlowProcessDao.findAll(pageable);
        for (WorkFlowProcess wp : page) {
            if (wp.getCodeStrategyId() != null) {
                Optional<WorkFlowProcessCodeStrategy> ocs = workFlowProcessCodeStrategyDao.findById(wp.getCodeStrategyId());
                if (ocs.isPresent()) {
                    wp.setCodeStrategyName(ocs.get().getName());
                }
            }
        }
        return page;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public WorkFlowProcess add(WorkFlowProcessBean bean) {
        WorkFlowProcess entity = new WorkFlowProcess();
        entity.setBizName(bean.getBizName());
        entity.setBizTypeName(bean.getBizTypeName());
        //设置表单组件唯一key
        entity = formatFormJsonKey(bean.getFormJson(), true, entity);
        entity.setType(bean.getType());
        entity.setPrintOpen(bean.getPrintOpen());
        entity.setLocationServiceOpen(bean.getLocationServiceOpen());
        entity.setAuthConfig(bean.getAuthConfig());
        entity.setCodeStrategyId(bean.getCodeStrategyId());
        entity.setProcessType(bean.getProcessType());
        entity.setSyncStatusOnOff(bean.getSyncStatusOnOff());
        Optional<WorkFlowProcessCodeStrategy> ocs = workFlowProcessCodeStrategyDao.findById(bean.getCodeStrategyId());
        if (ocs.isPresent()) {
            entity.setCodePrefix(ocs.get().getCodePrefix());
        }
        entity = workFlowProcessDao.save(entity);
        //保存默认的位置配置
        saveDefaultLocationConfig(entity);
        return entity;
    }

    private WorkFlowLocationConfig saveDefaultLocationConfig(WorkFlowProcess entity) {
        WorkFlowLocationConfig locationConfig = new WorkFlowLocationConfig();
        locationConfig.setProcessId(entity.getId());
        locationConfig.setComponentKeyName(IdUtil.simpleUUID());
        locationConfig.setComponentName(Constants.LOCATION_CONFIG_COMPONENT_NAME);
        locationConfig.setMapShowName(entity.getBizName());
        locationConfigDao.save(locationConfig);
        return locationConfig;
    }

    /**
     * 接口存在多个地方使用，且传参不一致，修改需谨慎
     *
     * @param bean
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void update(WorkFlowProcessBean bean) {
        WorkFlowProcess entity = workFlowProcessDao.findById(bean.getId()).get();
        int lastSyncStatusOnOff = entity.getSyncStatusOnOff();
        if (entity != null) {
            SpringBeanUtils.copyProperties(bean, entity, true);
            if (bean.getSyncStatusOnOff() == null) {
                entity.setSyncStatusOnOff(lastSyncStatusOnOff);
            }
            entity = formatFormJsonKey(bean.getFormJson(), false, entity);
            if (StringUtils.isNotBlank(bean.getAuthConfig())) {
                entity.setAuthConfig(bean.getAuthConfig());
            }
            if (bean.getCodeStrategyId() != null) {
                Optional<WorkFlowProcessCodeStrategy> ocs = workFlowProcessCodeStrategyDao.findById(bean.getCodeStrategyId());
                if (ocs.isPresent()) {
                    entity.setCodePrefix(ocs.get().getCodePrefix());
                }
            }
            entity.setUpdateBy(Context.getCurrentUserId());
            entity.setUpdateTime(new Date());
            workFlowProcessDao.save(entity);
            // 缓存组件信息
            saveComponentToCache(entity.getId(), bean.getFormJson(), entity.getTenentId(), entity.getOrgCode());
            WorkFlowLocationConfig config = locationConfigDao.findFirstByProcessId(entity.getId());
            if (config == null) {
                saveDefaultLocationConfig(entity);
            }
            if (bean.getSyncStatusOnOff() != null && Constant.SYNC_ON == bean.getSyncStatusOnOff() && Constant.SYNC_OFF == lastSyncStatusOnOff) {
                workFlowTaskProcessListService.asyncFormDataToStatisticData(bean.getId(), Context.getCurrentTenantId(), Context.getCompanyCode());
            }
        }
    }

    @Override
    public void saveComponentToCache(Long processId, String formJson, Long tenentId, String companyCode) {
        List<ComponentStatisticBO> components = findObjectFormJsonComponentType(formJson);
        String componentsJson = JSON.toJSONString(components);
        redisClient.hput(String.format(BaseConfigCodes.COMPONENT_COUNT_KEY, tenentId, companyCode), processId, componentsJson);
    }

    public List<ComponentStatisticBO> findObjectFormJsonComponentType(String formJsonStr) {
        List<ComponentStatisticBO> components = new ArrayList<>();
        List<String> componentTypes = ComponentCountEnum.getAllCountType();
        if (StringUtils.isNotBlank(formJsonStr)) {
            JSONObject formJson = JSON.parseObject(formJsonStr);
            Object temArrObj = formJson.get(WorkFlowConstants.FROM_JSON_KEY_TEMARR);
            if (temArrObj != null) {
                JSONArray temArr = JSONObject.parseArray(temArrObj.toString());
                for (Object tem : temArr) {
                    Map<String, Object> tableMap = JSONObject.parseObject(JSON.toJSONString(tem));
                    Object column1 = tableMap.get(WorkFlowConstants.FROM_JSON_KEY_COLUMN1);
                    if (WorkFlowConstants.FROM_JSON_KEY_TABLE.equals(column1)) {
                        continue;
                    }
                    Object tableArrObj = tableMap.get(WorkFlowConstants.FROM_JSON_KEY_TABLEARR);
                    JSONArray tableArr = JSONObject.parseArray(tableArrObj.toString());
                    for (Object table : tableArr) {
                        Map<String, Object> beanMap = JSONObject.parseObject(JSON.toJSONString(table));
                        Object typeObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_TYPE);
                        if (typeObj != null) {
                            String value = (String) typeObj;
                            if (componentTypes.contains(value)) {
                                if (ComponentCountEnum.INPUT.getCode().equals(value)) {
                                    Object labelObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_ANALYZABLE);
                                    if (labelObj == null || Boolean.FALSE.equals(labelObj)) {
                                        continue;
                                    }
                                }
                                if (ComponentCountEnum.DIALOG.getCode().equals(value)) {
                                    Object labelObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_DIA_TYPE);
                                    if (WorkFlowConstants.FROM_JSON_KEY_DIA_TYPE_MAP_PLACE.equals(labelObj)) {
                                        continue;
                                    }
                                }
                                Object labelObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_LABEL);
                                Object selfObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_SELF);
                                Object diaType = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_DIA_TYPE);
                                components.add(new ComponentStatisticBO((String) diaType, (String) typeObj, (String) labelObj, (String) selfObj));
                            }
                        }
                    }
                }
            }
        }
        return components;
    }

    private WorkFlowProcess formatFormJsonKey(String formJson, boolean isNew, WorkFlowProcess process) {
        if (StringUtils.isEmpty(formJson)) {
            return process;
        }
        JSONObject formJsonObj = JSON.parseObject(formJson);
        if (formJsonObj.get("temArr") == null) {
            return process;
        }
        JSONArray temArr = formJsonObj.getJSONArray("temArr");
        if (temArr == null || temArr.isEmpty()) {
            return process;
        }
        JSONObject formKeyLabelObj = new JSONObject();
        //遍历模板表单列表
        for (int i = 0; i < temArr.size(); i++) {
            JSONObject temObj = temArr.getJSONObject(i);
            if (temObj == null || temObj.getString("tableArr") == null) {
                continue;
            }
            //获取每个表单的组件列表
            JSONArray tableArr = JSON.parseArray(temObj.getString("tableArr"));
            if (tableArr == null || tableArr.isEmpty()) {
                continue;
            }
            //第一次创建表单组件，直接按顺序设置Key
            StringBuffer key = null;
            if (isNew) {
                // 给每个表单组件添加Key， 格式：
                for (int j = 0; j < tableArr.size(); j++) {
                    JSONObject comObj = tableArr.getJSONObject(j);
                    if (comObj != null) {
                        key = new StringBuffer("key_").append(UUID.randomUUID().toString());
                        //设置唯一key
                        comObj.put("key", key.toString().replace("-", ""));
                        //存储字段 key-label mapping 关系
                        formKeyLabelObj.put(comObj.getString("label"), key.toString());
                    }
                }
            } else {
                for (int j = 0; j < tableArr.size(); j++) {
                    JSONObject comObj = tableArr.getJSONObject(j);
                    if (comObj != null) {
                        if ((comObj.get("key") == null || "".equals(comObj.get("key").toString()))) {
                            key = new StringBuffer("key_").append(UUID.randomUUID().toString());
                            comObj.put("key", key.toString().replace("-", ""));
                        }
                        formKeyLabelObj.put(comObj.getString("label"), comObj.get("key").toString());
                    }

                }
            }
            temObj.put("tableArr", tableArr);

        }
        //添加默认字段
        formKeyLabelObj.put("状态", WorkFlowConstants.WORK_FLOW_TASK_STATUS_KEY);
        formKeyLabelObj.put("编号", WorkFlowConstants.WORK_FLOW_TASK_ID_KEY);
        process.setFormJson(formJsonObj.toJSONString());
        process.setFormKeyLabelJson(formKeyLabelObj.toJSONString());
        return process;
    }

    @Override
    public void update(WorkFlowProcess entity) {
        workFlowProcessDao.save(entity);
    }

    @Override
    public void saveProcessModelConfig(ProcessModelConfigBean bean) throws JsonProcessingException {
        WorkFlowProcess entity = workFlowProcessDao.findById(bean.getId()).get();
        if (entity != null) {
            entity.setModelJson(bean.getModelJson());
            workFlowProcessDao.save(entity);
        }
    }

    @Override
    public void saveProcessFormConfig(ProcessFormConfigBean bean) {
        WorkFlowProcess entity = workFlowProcessDao.findById(bean.getId()).get();
        if (entity != null) {
            entity.setFormJson(bean.getFormJson());
            workFlowProcessDao.save(entity);
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void deleteById(Long id) {

        workFlowProcessDao.deleteById(id);
        workFlowMenuDao.deleteAllByWorkFlowId(id);
    }

    @Override
    public void deleteMenuByMenuId(Long id) {
        workFlowMenuDao.deleteById(id);
    }

    @Override
    public WorkFlowProcessBean findDetailById(Long processId) {
        Optional<WorkFlowProcess> optional = findById(processId);
        WorkFlowProcessBean bean = new WorkFlowProcessBean();
        if (optional.isPresent()) {
            BeanUtils.copyProperties(optional.get(), bean);
            if (optional.get().getCodeStrategyId() != null) {
                Optional<WorkFlowProcessCodeStrategy> ocs = workFlowProcessCodeStrategyDao.findById(optional.get().getCodeStrategyId());
                if (ocs.isPresent()) {
                    bean.setCodeStrategyName(ocs.get().getName());
                }
            }
        }
        return bean;
    }

    /**
     * 部署业务流程
     *
     * @param processId 业务流程ID
     */
    @Override
    public Deployment deployWorkFlowProcess(Long processId) throws IOException, ApiCoreException {
        //根据业务流程ID 获取模板ID
        String modelId = getModelId(processId);
        //调用API 部署业务流程
        Deployment deployment = processAPI.deploy(modelId);

        if (deployment == null) {
            log.error("Process deployment error. processId {}", processId);
            throw new ApiCoreException(Status.PROCESS_CONTENT_IS_EMPTY);
        }
        // 保存流程部署信息
        Optional<WorkFlowProcess> optional = findById(processId);
        if (optional.isPresent()) {
            WorkFlowProcess process = optional.get();
            process.setDeploymentId(deployment.getId());
            process.setDeploymentName(deployment.getName());
            process.setDeploymentTime(LocalDateTime.now());
            workFlowProcessDao.save(process);
        } else {
            log.error("Process was not found. processId {}", processId);
            throw new ApiCoreException(Status.PROCESS_NOT_FIND_ERROR);
        }
        return deployment;
    }


    @Override
    public WorkFlowProcess getByModelId(String modelId) {
        return workFlowProcessDao.findByModelId(modelId);
    }

    @Override
    public List<BaseMenuFunction> listSystem() {
        return baseMenuFunctionDao.findByDepth(WorkFlowConstants.WORK_FLOW_SYSTEM_MENU_DEPTH);
    }

    @Override
    public WorkFlowProcess findByBizName(String bizName) {
        return workFlowProcessDao.findByBizName(bizName);
    }

    @Override
    public List<WorkFlowTaskNameBean> findTaskNameList(Long processId) {
        Optional<WorkFlowProcess> optionalProcess = workFlowProcessDao.findById(processId);
        List<WorkFlowTaskNameBean> taskNameList = new ArrayList<>();
        if (optionalProcess.isPresent()) {
            WorkFlowProcess process = optionalProcess.get();
            if (process.getTaskNameList() != null) {
                return JSONArray.parseArray(process.getTaskNameList(), WorkFlowTaskNameBean.class);
            }
        }
        return taskNameList;
    }

    @Override
    public List<WorkFlowProcessSimpleBean> findSimpleList() {
        List<WorkFlowProcess> list = workFlowProcessDao.findAll();
        List<WorkFlowProcessSimpleBean> simpleList = new ArrayList<>();
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(list)) {
            for (WorkFlowProcess w : list) {
                WorkFlowProcessSimpleBean s = new WorkFlowProcessSimpleBean();
                s.setWorkFlowId(w.getId());
                s.setWorkFlowName(w.getBizName());
                simpleList.add(s);
            }
        }
        return simpleList;
    }

    @Override
    public ResultBean dataSource(Integer type, Pageable pageable) {
        String modelType = ModelDataSourceTypes.getType(type);
        Assert.notNull(modelType, "不支持此数据源");
        if (modelType.equals(ModelDataSourceTypes.USER.getType())) {
            return baseUserService.getAllFields(pageable);
        } else if (modelType.equals(ModelDataSourceTypes.CONTRACTOR_STAFF.getType())) {
            return bpContractorStaffService.getAllFields(pageable);
        }
        return null;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public ResultBean locationConfigSave(WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> bean) {
        Long id = bean.getId();
        Long processId = bean.getProcessId();
        WorkFlowLocationConfig config;
        if (id == null) {
            config = new WorkFlowLocationConfig();
            WorkFlowLocationConfig locationConfig = locationConfigDao.findFirstByProcessId(processId);
            if (locationConfig != null) {
                log.warn("此流程已有配置，在已有配置上修改即可,配置如下:{}", JSON.toJSONString(locationConfig));
                return ResultBean.fail(101, "此流程已有配置，在已有配置上修改即可");
            }
        } else {
            config = locationConfigDao.findById(id).orElseThrow(() -> new IllegalArgumentException("基础配置数据不存在"));
        }
        WorkFlowProcess process = workFlowProcessDao.findById(bean.getProcessId()).orElseThrow(() -> new IllegalArgumentException("此业务流程不存在"));
        //开始时间/结束时间 判断
        String showTimeType = bean.getShowTimeType();
        if (WorkFlowShowTypes.BUSINESS_RANGE.getType().equals(showTimeType)) {
            String startTimeKey = bean.getStartTimeKey();
            String endTimeKey = bean.getEndTimeKey();
            String startTimeFormat = null;
            String endTimeFormat = null;
            Assert.notNull(startTimeKey, "开始时间不能为空");
            Assert.notNull(endTimeKey, "开始时间不能为空");
            //判断process form_json中是否含有此key
            String formJson = process.getFormJson();
            if (StringUtils.isEmpty(formJson)) {
                return ResultBean.fail(101, "请新配置业务流程");
            }
            Pair<String, String> pair = getTimeFormat(formJson, startTimeKey, endTimeKey);
            startTimeFormat = pair.getKey();
            endTimeFormat = pair.getValue();
            Assert.notNull(startTimeFormat, "请选择正确的开始时间组件");
            Assert.notNull(endTimeFormat, "请选择正确的结束时间组件");
        } else if (WorkFlowShowTypes.FLOW_NODE_RANGE.getType().equals(showTimeType)) {
            Assert.isTrue(!CollectionUtils.isEmpty(bean.getFlowNodeList()), "请选择流程节点");
            config.setFlowNode(JSON.toJSONString(bean.getFlowNodeList()));
        }
        //启用位置服务时对绑定组件内容更新，不启用则保留之前内容再起启用时显示
        if (bean.getLocationServiceOpen()) {
            BeanUtils.copyProperties(bean, config, "id");
            BaseAttachmentBean iconUpload = bean.getIconUpload();
            config.setIconUpload(iconUpload == null ? "" : JSON.toJSONString(iconUpload));
            if (bean.getSnapshotOpen() == null) {
                config.setSnapshotOpen(0);
            }
            if (bean.getSignatureOpen() == null) {
                config.setSignatureOpen(1);
            }
            config = locationConfigDao.save(config);
        }
        //保存开启位置服务状态
        process.setLocationServiceOpen(bean.getLocationServiceOpen());
        workFlowProcessDao.save(process);

        //大屏专栏配置
        WorkFlowScreenConfigBean screenConfigBean = bean.getScreenConfig();
        if (screenConfigBean != null) {
            Long screenConfigBeanId = screenConfigBean.getId();
            Long processId1 = screenConfigBean.getProcessId();
            Assert.isTrue(processId.equals(processId1), "processId 不一致");
            WorkFlowScreenConfig screenConfig;
            if (screenConfigBeanId == null) {
                screenConfig = new WorkFlowScreenConfig();
                WorkFlowScreenConfig screenConfig1 = screenConfigDao.findFirstByProcessId(processId);
                if (screenConfig1 != null) {
                    log.warn("此流程已有大屏专栏配置，在已有配置上修改即可,配置如下:{}", JSON.toJSONString(screenConfig1));
                    return ResultBean.fail(101, "此流程已有大屏专栏配置，在已有配置上修改即可");
                }
                BeanUtils.copyProperties(screenConfigBean, screenConfig);
                screenConfig.setShow(0);
                screenConfig.setValueShowButton(0);
                screenConfig.setValueShow(0);
            } else {
                screenConfig = screenConfigDao.findById(screenConfigBeanId).orElseThrow(() -> new IllegalArgumentException("可视化大屏数据不存在"));
                BeanUtils.copyProperties(screenConfigBean, screenConfig);
            }
            screenConfig.setEnvironmentPointFlag(0);
            screenConfigDao.save(screenConfig);
        }

        //电子围栏报警配置
        WorkFlowRailAlarmConfigBean railAlarmConfigBean = bean.getRailAlarmConfig();
        if (railAlarmConfigBean != null) {
            Long railAlarmConfigId = railAlarmConfigBean.getId();
            Long processId2 = railAlarmConfigBean.getProcessId();
            Assert.isTrue(processId.equals(processId2), "processId 不一致");
            WorkFlowRailAlarmConfig alarmConfig;
            if (railAlarmConfigId == null) {
                alarmConfig = new WorkFlowRailAlarmConfig();
                WorkFlowRailAlarmConfig alarmConfig1 = alarmConfigDao.findFirstByProcessId(processId);
                if (alarmConfig1 != null) {
                    log.warn("此流程已有电子围栏报警配置，在已有配置上修改即可,配置如下:{}", JSON.toJSONString(alarmConfig1));
                    return ResultBean.fail(101, "此流程已有电子围栏报警配置，在已有配置上修改即可");
                }
            } else {
                alarmConfig = alarmConfigDao.findById(railAlarmConfigId).orElseThrow(() -> new IllegalArgumentException("电子围栏报警数据不存在"));
            }
            //判断生效时间
            String effectiveTime = railAlarmConfigBean.getEffectiveTime();
            if (WorkFlowShowTypes.FLOW_NODE_RANGE.getType().equals(effectiveTime)) {
                String startNode = railAlarmConfigBean.getStartNode();
                String endNode = railAlarmConfigBean.getEndNode();
                Assert.isTrue(startNode != null && endNode != null, "开始节点和结束节点不能为空");
                Assert.isTrue(!startNode.equals(endNode), "开始节点不能和结束节点重复");
            } else if (WorkFlowShowTypes.TIME_COMPONENT_RANGE.getType().equals(effectiveTime)) {
                Assert.isTrue(railAlarmConfigBean.getStartTimeKey() != null &&
                        railAlarmConfigBean.getEndTimeKey() != null, "开始时间和结束时间不能为空");
            } else {
                throw new IllegalArgumentException("电子围栏报警-不支持此生效时间类型");
            }
            BeanUtils.copyProperties(railAlarmConfigBean, alarmConfig);
            alarmConfigDao.save(alarmConfig);
        }
        return ResultBean.success(config.getId());
    }

    private Pair<String, String> getTimeFormat(String formJson, String startTimeKey, String endTimeKey) {
        String startTimeFormat = null;
        String endTimeFormat = null;
        JSONObject formJsonObject = JSONObject.parseObject(formJson);
        JSONArray jsonArray = formJsonObject.getJSONArray("temArr");
        for (int i = 0; i < jsonArray.size(); i++) {
            JSONObject jsonObject = (JSONObject) jsonArray.get(i);
            JSONArray tableArr = jsonObject.getJSONArray("tableArr");
            for (int j = 0; j < tableArr.size(); j++) {
                JSONObject tableJson = (JSONObject) tableArr.get(j);
                String key = tableJson.getString("key");
                if (startTimeKey.equals(key)) {
                    startTimeFormat = tableJson.getString("format");
                }
                if (endTimeKey.equals(key)) {
                    endTimeFormat = tableJson.getString("format");
                }
            }
        }
        return new Pair<>(startTimeFormat, endTimeFormat);
    }

    @Override
    public ResultBean processLocationConfig(Long processId) throws ApiCoreException {
        Optional<WorkFlowProcess> optionalProcess = workFlowProcessDao.findById(processId);
        if (!optionalProcess.isPresent()) {
            throw new ApiCoreException(Status.PROCESS_NOT_FIND_ERROR);
        }
        WorkFlowProcess process = optionalProcess.get();
        //新增默认位置配置
        WorkFlowLocationConfig config = locationConfigDao.findFirstByProcessId(processId);
        if (config == null) {
            config = saveDefaultLocationConfig(process);
        }
        WorkFlowConfigDeployBean workFlowConfigDeployBean = new WorkFlowConfigDeployBean(config.getComponentKeyName(), true, process.getLocationServiceOpen());
        WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean = getLocationConfigByProcessId(processId);
        if (configBean == null) {
            return ResultBean.success(workFlowConfigDeployBean);
        } else {
            configBean.setLocationServiceOpen(process.getLocationServiceOpen());
        }
        return ResultBean.success(configBean);
    }

    @Override
    public WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> getLocationConfigByProcessId(Long processId) {
        WorkFlowLocationConfig locationConfig = locationConfigDao.findFirstByProcessId(processId);
        if (locationConfig == null) {
            return null;
        }
        WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean = new WorkFlowLocationConfigBean<>();
        BeanUtils.copyProperties(locationConfig, configBean);
        String iconUpload = locationConfig.getIconUpload();
        configBean.setIconUpload(StringUtils.isEmpty(iconUpload) ? null : JSONObject.parseObject(iconUpload, BaseAttachmentBean.class));
        configBean.setDeploy(true);
        configBean.setFlowNodeList(locationConfig.getFlowNode() == null ? null : JSON.parseArray(locationConfig.getFlowNode(), String.class));
        //大屏专栏
        if (locationConfig.isScreenColumnOpen()) {
            WorkFlowScreenConfig screenConfig = screenConfigDao.findFirstByProcessId(processId);
            if (screenConfig == null) {
                configBean.setScreenConfig(null);
            } else {
                //避免showOrder为空的情况
                if (screenConfig.getShowOrder() == null) {
                    screenConfig.setShowOrder(0);
                    screenConfigDao.save(screenConfig);
                }
                WorkFlowScreenConfigBean screenConfigBean = new WorkFlowScreenConfigBean();
                BeanUtils.copyProperties(screenConfig, screenConfigBean);
                if (screenConfigBean.getTypeId() != null) {
                    screenTypeDao.findById(screenConfigBean.getTypeId()).ifPresent(r -> screenConfigBean.setTypeName(r.getTypeName()));
                }
                configBean.setScreenConfig(screenConfigBean);
            }
        }
        //电子围栏报警
//        if (locationConfig.isRailAlarmOpen()) {
        WorkFlowRailAlarmConfig alarmConfig = alarmConfigDao.findFirstByProcessId(processId);
        if (alarmConfig != null) {
            WorkFlowRailAlarmConfigBean alarmConfigBean = new WorkFlowRailAlarmConfigBean();
            BeanUtils.copyProperties(alarmConfig, alarmConfigBean);
            configBean.setRailAlarmConfig(alarmConfigBean);
        }
//        }
        return configBean;
    }


    @Override
    public Map<Long, WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> getLocationConfigMapByProcessIds(List<Long> processIds) {
        Map<Long, WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> map = new HashMap<>();
        List<WorkFlowLocationConfig> locationConfigs = locationConfigDao.findByProcessIdIn(processIds);
        List<WorkFlowScreenConfig> flowScreenConfigs = screenConfigDao.findByProcessIdIn(processIds);
        if (CollectionUtils.isEmpty(locationConfigs)) {
            return map;
        }
        Map<Long, WorkFlowLocationConfig> locationConfigMap = locationConfigs.stream().collect(Collectors.toMap(WorkFlowLocationConfig::getProcessId, e -> e));
        Map<Long, WorkFlowScreenConfig> flowScreenConfigMap = flowScreenConfigs.stream().collect(Collectors.toMap(WorkFlowScreenConfig::getProcessId, e -> e));
        for (Long processId : processIds) {
            WorkFlowLocationConfig locationConfig = locationConfigMap.get(processId);
            // 过滤没有配置大屏展示的流程
            if(locationConfig == null){
                continue;
            }
            WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean = new WorkFlowLocationConfigBean<>();
            BeanUtils.copyProperties(locationConfig, configBean);
            String iconUpload = locationConfig.getIconUpload();
            configBean.setIconUpload(StringUtils.isEmpty(iconUpload) ? null : JSONObject.parseObject(iconUpload, BaseAttachmentBean.class));
            configBean.setDeploy(true);
            configBean.setFlowNodeList(locationConfig.getFlowNode() == null ? null : JSON.parseArray(locationConfig.getFlowNode(), String.class));
            //大屏专栏
            if (locationConfig.isScreenColumnOpen()) {
                WorkFlowScreenConfig screenConfig = flowScreenConfigMap.get(processId);
                if (screenConfig == null) {
                    configBean.setScreenConfig(null);
                } else {
                    //避免showOrder为空的情况
                    if (screenConfig.getShowOrder() == null) {
                        screenConfig.setShowOrder(0);
                        screenConfigDao.save(screenConfig);
                    }
                    WorkFlowScreenConfigBean screenConfigBean = new WorkFlowScreenConfigBean();
                    BeanUtils.copyProperties(screenConfig, screenConfigBean);
                    if (screenConfigBean.getTypeId() != null) {
                        screenTypeDao.findById(screenConfigBean.getTypeId()).ifPresent(r -> screenConfigBean.setTypeName(r.getTypeName()));
                    }
                    configBean.setScreenConfig(screenConfigBean);
                }
            }
            //电子围栏报警
            WorkFlowRailAlarmConfig alarmConfig = alarmConfigDao.findFirstByProcessId(processId);
            if (alarmConfig != null) {
                WorkFlowRailAlarmConfigBean alarmConfigBean = new WorkFlowRailAlarmConfigBean();
                BeanUtils.copyProperties(alarmConfig, alarmConfigBean);
                configBean.setRailAlarmConfig(alarmConfigBean);
            }
            map.put(processId, configBean);
        }
        return map;
    }

    /**
     * 保存有毒可燃气体大屏配置
     *
     * @param saveType
     */
    @Override
    public void saveConfigFromMhPointType(MhMonitoringType saveType) {
        WorkFlowScreenConfig screenConfig = workFlowScreenConfigDao.findByBizTypeCodeAndEnvironmentPointFlag(saveType.getCode(), 1);
        if (screenConfig == null) {
            screenConfig = new WorkFlowScreenConfig();
            screenConfig.setShow(1);
            screenConfig.setShowOrder(1000);
            screenConfig.setValueShow(1);
            screenConfig.setValueShowButton(1);
            screenConfig.setEnvironmentPointFlag(1);
            //重大危险源大屏专栏id
            WorkFlowScreenType screenType = screenTypeDao.findByCode("mh");
            if (saveType != null) {
                screenConfig.setTypeId(screenType.getId());
            } else {
                throw new IllegalArgumentException("危险源大屏专栏不存在");
            }
        }
        screenConfig.setBizTypeCode(saveType.getCode());
        screenConfig.setBizTypeName(saveType.getName());
        workFlowScreenConfigDao.save(screenConfig);
    }

    /**
     * 保存编码设置
     *
     * @param bean
     * @return
     */
    @Override
    public WorkFlowProcessCodeStrategy saveCodeStrategy(WorkFlowProcessCodeStrategyBean bean) {
        WorkFlowProcessCodeStrategy strategy = new WorkFlowProcessCodeStrategy();
        if (bean.getId() != null) {
            strategy = workFlowProcessCodeStrategyDao.findById(bean.getId()).orElseThrow(() -> new IllegalArgumentException("编号配置不存在"));
        }
        BeanUtils.copyProperties(bean, strategy);
        if (bean.getId() == null) {
            strategy.setBizCodeNumber(1);
        }
        //编码为空设置为""
        if (bean.getCodePrefix() == null) {
            strategy.setCodePrefix("");
        }
        if (strategy.getName() == null) {
            throw new IllegalArgumentException("名称不能为空");
        }
        // 如果不包含日期设置为-1
        if (bean.getIsDateFormat() != null && !bean.getIsDateFormat()) {
            strategy.setTimestamp(-1);
        }
        strategy = workFlowProcessCodeStrategyDao.save(strategy);
        int num = workFlowProcessCodeStrategyDao.countByCodePrefix(strategy.getCodePrefix());
        int nu = workFlowProcessCodeStrategyDao.countByName(strategy.getName());
        if (num > 1) {
            throw new IllegalArgumentException("编码前缀已存在");
        }
        if (nu > 1) {
            throw new IllegalArgumentException("名称已存在");
        }
        return strategy;
    }

    /**
     * 查看编码设置
     *
     * @param id 流程id
     * @return
     */
    @Override
    public WorkFlowProcessCodeStrategyBean findCodeStrategyById(Long id) {
        WorkFlowProcessCodeStrategyBean bean = new WorkFlowProcessCodeStrategyBean();
        WorkFlowProcessCodeStrategy strategy = workFlowProcessCodeStrategyDao.findById(id).get();
        BeanUtils.copyProperties(strategy, bean);
        bean.setIsDateFormat(strategy.getTimestamp() != null && strategy.getTimestamp() != -1);
        return bean;
    }

    /**
     * 删除环境监测点大屏配置
     *
     * @param type
     */
    @Override
    public void deleteEnvironmentPointConfig(MhMonitoringType type) {
        if (type.getCode() != null) {
            workFlowScreenConfigDao.deleteByBizTypeCodeAndEnvironmentPointFlag(type.getCode(), 1);
        }
    }

    /**
     * 分页查看编码规则
     *
     * @param page
     * @param name
     * @return
     */
    @Override
    public ResultBean pageCodeStrategy(Pageable page, String name) {
        List<WorkFlowProcessCodeStrategy> strategyList = new ArrayList<>();
        List<WorkFlowProcessCodeStrategyBean> beanList = new ArrayList<>();
        int num = 0;
        if (name != null) {
            strategyList = workFlowProcessCodeStrategyDao.findByNameLike(name);
        } else {
            strategyList = workFlowProcessCodeStrategyDao.findAll();
        }
        if (!CollectionUtils.isEmpty(strategyList)) {
            num = strategyList.size();
            strategyList = PageableUtil.getList(page, strategyList);
            for (WorkFlowProcessCodeStrategy strategy : strategyList) {
                WorkFlowProcessCodeStrategyBean bean = new WorkFlowProcessCodeStrategyBean();
                BeanUtils.copyProperties(strategy, bean);
                bean.setIsDateFormat(strategy.getTimestamp() != null && strategy.getTimestamp() != -1);
                beanList.add(bean);
            }
            return ResultBean.pageData(beanList, num);
        }

        return ResultBean.success(strategyList);
    }

    @Override
    public ResultBean deleteCodeStrategyById(Long id) {
        List<WorkFlowProcess> list = workFlowProcessDao.findByCodeStrategyId(id);
        if (!org.springframework.util.CollectionUtils.isEmpty(list)) {
            throw new IllegalArgumentException("请先解除与业务流程的绑定关系");
        }
        workFlowProcessCodeStrategyDao.deleteById(id);
        return ResultBean.success("");
    }

    @Override
    public List<SimpleSelectListBean> getByBizTypeName(String bizTypeName) {
        List<SimpleSelectListBean> beanList = new ArrayList<>();
        List<WorkFlowProcess> processList = workFlowProcessDao.findByBizTypeName(bizTypeName);
        if (!CollectionUtils.isEmpty(processList)) {
            processList.forEach(process -> {
                SimpleSelectListBean bean = new SimpleSelectListBean();
                bean.setValue(process.getId());
                bean.setLabel(process.getBizName());
                beanList.add(bean);
            });
        }
        return beanList;
    }

    @Override
    public WorkFlowProcess getWorkFlowProcessByDefinitionKey(String definitionKey) {
        return workFlowProcessDao.getWorkFlowProcessByDefinitionKey(definitionKey);
    }

    @Override
    public List<WorkFlowProcess> findByBizNameList(String bizName) {
        return workFlowProcessDao.findByBizNameList(bizName);
    }

    @Override
    public List<ComponentStatisticBO> getFields(String processName) {
        WorkFlowProcess workFlowProcess = workFlowProcessDao.findByBizName(processName);
        String jsonStr = workFlowProcess.getFormJson();
        List<ComponentStatisticBO> list = transFormBO(jsonStr);
        return list;
    }

    @Override
    public List<ComponentStatisticBO> getV2Fields(String processName) {
        List<ComponentStatisticBO> list = new ArrayList<>();
        HttpHeaders headers = getHeaders();
        HttpEntity<JSONObject> httpEntity = new HttpEntity<>(headers);
        //获取配置的key
        BaseConfig config = baseConfigService.findFirstConfig(BaseConfigCodes.RISK_HIDDEN_DANGER_PROCESS_KEY);
        BaseConfig ipConfig = baseConfigService.findFirstConfig(BaseConfigCodes.WORKFLOW_IP_ADDRESS);
        if (config == null || StringUtils.isBlank(config.getValue())) {
            throw new IllegalArgumentException("隐患治理流程在新版本业务流程Key未配置");
        }
        //获取新版流程引擎的服务地址
        String procDefKey = config.getValue();
        String url = "http://127.0.0.1:8886";
        if (ipConfig != null && StringUtils.isNotBlank(ipConfig.getValue())) {
            url = ipConfig.getValue();
        }
        BaseConfig typeConfig = baseConfigService.findFirstConfig(BaseConfigCodes.WORKFLOW_TYPES);
        if (typeConfig != null) {
            String[] strings = typeConfig.getValue().split(",");
            for (String string : strings) {
                if (WorkFlowFiledTypeEnum.find(string)==null) {
                    continue;
                }
                ResponseEntity<String> entity = restTemplate.exchange(url + "/api/blade-workflow/design/form/comp/list?procDefKey=" + procDefKey + "&types=" + string,
                        HttpMethod.GET, httpEntity, String.class);
                JSONObject jsonObject = JSON.parseObject(entity.getBody());
                if (jsonObject != null && jsonObject.get("code").equals(200)) {
                    list.addAll(transForm(jsonObject));
                }
            }
        }
        return list;
    }

    /**
     * 转换
     * @param jsonObject
     * @return
     */
    public List<ComponentStatisticBO> transForm(JSONObject jsonObject){
        List<ComponentStatisticBO> list=new ArrayList<>();
        String dataStr = jsonObject.getString("data");
        List<JSONObject> array = JSONArray.parseArray(dataStr, JSONObject.class);
        if (org.apache.commons.collections4.CollectionUtils.isNotEmpty(array)) {
            for (JSONObject object : array) {
                ComponentStatisticBO bo = new ComponentStatisticBO();
                bo.setKey(object.getString("prop"));
                bo.setLabel(object.getString("label"));
                bo.setComponentType(object.getString("type"));
                list.add(bo);
            }
        }
        return list;
    }


    private HttpHeaders getHeaders() {
        HttpHeaders httpHeaders = new HttpHeaders();
        httpHeaders.set("user-id", "" + Context.getCurrentUser().getRealUserId());
        httpHeaders.set("user-name", "" + Context.getCurrentUser().getRealName());
        httpHeaders.set("Authorization", "Basic c2FiZXI6c2FiZXJfc2VjcmV0");
        httpHeaders.set("app-id", "mvAmIwYJ7x6y0EADQvUb");
        httpHeaders.set("tenant-id", Context.getCurrentTenantId() + "");
        httpHeaders.set("org-code", Context.getCompanyCode());
        httpHeaders.set("signature", "30ca19ac3d133b30b9243ed61646136f7818a3d85e6a70a3bfaa68d3d64566c3");
        httpHeaders.set("Accept", "application/json");
        return httpHeaders;
    }

    public List<ComponentStatisticBO> transFormBO(String formJsonStr) {
        List<ComponentStatisticBO> components = new ArrayList<>();
        if (StringUtils.isNotBlank(formJsonStr)) {
            JSONObject formJson = JSON.parseObject(formJsonStr);
            Object temArrObj = formJson.get(WorkFlowConstants.FROM_JSON_KEY_TEMARR);
            if (temArrObj != null) {
                JSONArray temArr = JSONObject.parseArray(temArrObj.toString());
                for (Object tem : temArr) {
                    Map<String, Object> tableMap = JSONObject.parseObject(JSON.toJSONString(tem));
                    Object column1 = tableMap.get(WorkFlowConstants.FROM_JSON_KEY_COLUMN1);
                    if (WorkFlowConstants.FROM_JSON_KEY_TABLE.equals(column1)) {
                        continue;
                    }
                    Object tableArrObj = tableMap.get(WorkFlowConstants.FROM_JSON_KEY_TABLEARR);
                    JSONArray tableArr = JSONObject.parseArray(tableArrObj.toString());
                    for (Object table : tableArr) {
                        Map<String, Object> beanMap = JSONObject.parseObject(JSON.toJSONString(table));
                        Object typeObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_TYPE);
                        if (typeObj != null) {
                            String value = (String) typeObj;
                                if (ComponentCountEnum.INPUT.getCode().equals(value)) {
                                    Object labelObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_ANALYZABLE);
                                    if (labelObj == null || Boolean.FALSE.equals(labelObj)) {
                                        continue;
                                    }
                                }
                                if (ComponentCountEnum.DIALOG.getCode().equals(value)) {
                                    Object labelObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_DIA_TYPE);
                                    if (WorkFlowConstants.FROM_JSON_KEY_DIA_TYPE_MAP_PLACE.equals(labelObj)) {
                                        continue;
                                    }
                                }
                                Object labelObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_LABEL);
                                Object selfObj = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_SELF);
                                Object diaType = beanMap.get(WorkFlowConstants.FROM_JSON_KEY_DIA_TYPE);
                                components.add(new ComponentStatisticBO((String) diaType, (String) typeObj, (String) labelObj, (String) selfObj));
                        }
                    }
                }
            }
        }
        return components;
    }
    /**
     * @param searchBean
     * @return
     */
    @Override
    public ResultBean workFlowScreen(WorkFlowSearchBean searchBean) {
        List<WorkFlowProcess> processList = null;
        if (StringUtils.isNotBlank(searchBean.getBizTypeName())) {
            if (searchBean.getTypeId() == null) {
                processList = workFlowProcessDao.findByBizTypeNames(Lists.newArrayList(searchBean.getBizTypeName()));
            } else {
                processList = workFlowProcessDao.findByBizTypeNameAndTypeId(searchBean.getBizTypeName(), searchBean.getTypeId());
            }
        } else if (StringUtils.isBlank(searchBean.getBizTypeName()) && searchBean.getTypeId() != null) {
            List<String> names = workFlowScreenConfigDao.findBizTypeNameListByTypeIdAndEnvironmentFlagIsNull(searchBean.getTypeId());
            if (!CollectionUtils.isEmpty(names)) {
                processList = workFlowProcessDao.findByBizTypeNames(names);
            } else {
                return ResultBean.success(new ArrayList<>());
            }
        }

        if (CollectionUtils.isEmpty(processList)) {
            return ResultBean.success(new ArrayList<>());
        }
        List<WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> resultList = Lists.newArrayList();
        processList.stream().forEach(r -> {
            Long processId = r.getId();
            //获取每个process的大屏,报警配置
            WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean = getLocationConfigByProcessId(processId);
            if (configBean == null) {
                return;
            }
            String showTimeType = configBean.getShowTimeType();
            List<WorkFlowTask> taskList;
            if (WorkFlowShowTypes.BUSINESS_RANGE.getType().equals(showTimeType)) {
                String startTimeKey = configBean.getStartTimeKey();
                String endTimeKey = configBean.getEndTimeKey();
                Pair<String, String> pair = getTimeFormat(r.getFormJson(), startTimeKey, endTimeKey);
                String startTimeFormat = pair.getKey();
                String endTimeFormat = pair.getValue();
                if (startTimeFormat == null || endTimeFormat == null) {
                    return;
                }
                taskList = workFlowTaskDao.findScreenTaskByProcessIdAndParentId(processId, 0L);
                Iterator<WorkFlowTask> iterator = taskList.iterator();
                while (iterator.hasNext()) {
                    WorkFlowTask task = iterator.next();
                    String formData = task.getFormData();
                    JSONObject jsonObject = JSONObject.parseObject(formData);
                    String startTimeString = jsonObject.getString(startTimeKey);
                    String endTimeString = jsonObject.getString(endTimeKey);
                    SimpleDateFormat startFormat = SimpleDateFormatCache.getFormat(startTimeFormat);
                    SimpleDateFormat endFormat = SimpleDateFormatCache.getFormat(endTimeFormat);
                    try {
                        Date startTime = startFormat.parse(startTimeString);
                        Date endTime = endFormat.parse(endTimeString);
                        Date now = new Date();
                        if (now.before(startTime) || now.after(endTime)) {
                            iterator.remove();
                        }
                    } catch (Exception e) {
                        log.error("流程引擎-监控大屏 日期解析出错:" + e.getMessage());
                    }
                }
            } else if (WorkFlowShowTypes.FLOW_NODE_RANGE.getType().equals(showTimeType)) {
                List<String> flowNodeList = configBean.getFlowNodeList();
                taskList = workFlowTaskDao.findScreenTaskByParam(processId, flowNodeList, 0L);
            } else {
                taskList = workFlowTaskDao.findScreenTaskByProcessIdAndParentId(processId, 0L);
            }
            configBean.setTaskList(taskList);
            resultList.add(configBean);
        });
        //基于screenConfig中的显示顺序排序，从小到大
        List<WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> nullList = resultList.stream().filter(r -> r.getScreenConfig() == null).collect(Collectors.toList());
        List<WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> sortedList = resultList.stream().filter(r -> r.getScreenConfig() != null && r.getScreenConfig().getTypeId() != null)
                .sorted(Comparator.comparing(r -> r.getScreenConfig().getShowOrder())).collect(Collectors.toList());
        Map<Long, List<WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>>> map = sortedList.stream().collect(Collectors.groupingBy(r -> r.getScreenConfig().getTypeId()));
        List<WorkFlowScreenDto> dtoList = Lists.newArrayList();
        for (Long typeId : map.keySet()) {
            Optional<WorkFlowScreenType> owt = screenTypeDao.findById(typeId);
            if (owt.isPresent()) {
                String typeCode = owt.get().getCode();
                List<WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> list = map.get(typeId);
                Map<Long, WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> configBeanMap = list.stream().collect(Collectors.toMap(r -> r.getProcessId(), r -> r));
                List<WorkFlowTask> taskList = Lists.newArrayList();
                for (WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean : list) {
                    taskList.addAll(configBean.getTaskList());
                }
                List<WorkFlowTask> totalTaskList = new ArrayList<>(taskList.size());
                for (WorkFlowTask task : taskList) {
                    WorkFlowTask workFlowTask = new WorkFlowTask();
                    BeanUtils.copyProperties(task, workFlowTask);
                    totalTaskList.add(workFlowTask);
                }
                //taskList筛选
                if (StringUtils.isNotBlank(searchBean.getBizTypeName())) {
                    if (searchBean != null) {
                        List<WorkFlowTaskSearchFieldBean> searchList = searchBean.getSearchList();
                        if (!org.springframework.util.CollectionUtils.isEmpty(searchList)) {
                            Iterator<WorkFlowTask> iterator = taskList.iterator();
                            while (iterator.hasNext()) {
                                WorkFlowTask next = iterator.next();
                                String formData = next.getFormData();
                                removeData(searchList, iterator, formData);
                            }
                        }
                    }
                    int length = taskList.size();
                    //分页截取
                    Integer page = 0;
                    Integer size = 25;
                    if (searchBean != null) {
                        page = searchBean.getPage();
                        size = searchBean.getSize();
                        if (page == null || size == null) {
                            page = 0;
                            size = 25;
                        }
                    }
                    List<WorkFlowTask> tempList = PageableUtil.getList(page, size, taskList);
                    if (searchBean.getTypeFlag().equals("page")) {
                        dtoList.add(new WorkFlowScreenDto(configBeanMap, null, null, tempList, length, typeCode));
                    } else if (searchBean.getTypeFlag().equals("all")) {
                        dtoList.add(new WorkFlowScreenDto(configBeanMap, taskList, null, null, length, typeCode));
                    }

                } else {
                    dtoList.add(new WorkFlowScreenDto(configBeanMap, totalTaskList, null, null, null, typeCode));
                }
            }
        }
        for (WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean : nullList) {
            Map<Long, WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> configBeanMap = new HashMap<>();
            configBeanMap.put(configBean.getProcessId(), configBean);
            if (StringUtils.isNotBlank(searchBean.getBizTypeName())) {
                dtoList.add(new WorkFlowScreenDto(configBeanMap, null, null));
            } else if (searchBean.getTypeId() != null) {
                dtoList.add(new WorkFlowScreenDto(configBeanMap, configBean.getTaskList(), null));
            }

        }
        //去除原configBean中的taskList
        for (WorkFlowScreenDto dto : dtoList) {
            Map<Long, WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> dtoMap = dto.getMap();
            if (dtoMap != null) {
                for (Long aLong : dtoMap.keySet()) {
                    WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> tempBean = dtoMap.get(aLong);
                    if (tempBean != null) {
                        tempBean.setTaskList(null);
                    }
                }
            }
        }
        if (StringUtils.isNotBlank(searchBean.getBizTypeName())) {
            if (org.springframework.util.CollectionUtils.isEmpty(dtoList)) {
                return ResultBean.success(new WorkFlowScreenDto());
            } else {
                return ResultBean.success(dtoList.get(0));
            }
        } else if (searchBean.getTypeId() != null) {
            return ResultBean.success(dtoList);
        } else {
            return ResultBean.success(new ArrayList<>());
        }
    }

    @Override
    public ResultBean workFlowScreenIconByCompany(String orgCode, Long tenentId, String bizName) {
        List<WorkFlowProcess> processList = null;
        List<String> bizNameList = null;
        if (StringUtils.isBlank(bizName)) {
            bizNameList = workFlowProcessDao.findBizNamesByLocationServiceOpen(orgCode, tenentId);
        } else {
            bizNameList = Lists.newArrayList(bizName);
        }
        if (CollectionUtil.isNotEmpty(bizNameList)) {
            processList = workFlowProcessDao.findByBizNamesAndCompany(Lists.newArrayList(bizNameList), orgCode, tenentId);
        }
        if (CollectionUtils.isEmpty(processList)) {
            return ResultBean.success(new ArrayList<>());
        }
        List<WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> resultList = Lists.newArrayList();
        ArrayList<WorkFlowTaskSimpleView> simpleTaskList = new ArrayList<>();
        for (WorkFlowProcess r : processList) {
            Long processId = r.getId();
            //获取每个process的大屏配置
            WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean = getLocationConfigByProcessId(processId);
            if (configBean == null) {
                continue;
            }
            String showTimeType = configBean.getShowTimeType();
            List<WorkFlowTask> taskList;
            if (WorkFlowShowTypes.BUSINESS_RANGE.getType().equals(showTimeType)) {
                String startTimeKey = configBean.getStartTimeKey();
                String endTimeKey = configBean.getEndTimeKey();
                Pair<String, String> pair = getTimeFormat(r.getFormJson(), startTimeKey, endTimeKey);
                String startTimeFormat = pair.getKey();
                String endTimeFormat = pair.getValue();
                if (startTimeFormat == null || endTimeFormat == null) {
                    continue;
                }
                taskList = workFlowTaskDao.findScreenTaskByProcessIdAndParentId(processId, 0L);
                Iterator<WorkFlowTask> iterator = taskList.iterator();
                while (iterator.hasNext()) {
                    WorkFlowTask task = iterator.next();
                    String formData = task.getFormData();
                    JSONObject jsonObject = JSONObject.parseObject(formData);
                    String startTimeString = jsonObject.getString(startTimeKey);
                    String endTimeString = jsonObject.getString(endTimeKey);
                    SimpleDateFormat startFormat = SimpleDateFormatCache.getFormat(startTimeFormat);
                    SimpleDateFormat endFormat = SimpleDateFormatCache.getFormat(endTimeFormat);
                    try {
                        Date startTime = startFormat.parse(startTimeString);
                        Date endTime = endFormat.parse(endTimeString);
                        Date now = new Date();
                        if (now.before(startTime) || now.after(endTime)) {
                            iterator.remove();
                        }
                    } catch (Exception e) {
                        log.error("流程引擎-监控大屏 日期解析出错:" + e.getMessage());
                    }
                }
            } else if (WorkFlowShowTypes.FLOW_NODE_RANGE.getType().equals(showTimeType)) {
                List<String> flowNodeList = configBean.getFlowNodeList();
                taskList = workFlowTaskDao.findScreenTaskByParam(processId, flowNodeList, 0L);
            } else {
                taskList = workFlowTaskDao.findScreenTaskByProcessIdAndParentId(processId, 0L);
            }
            // configBean.setTaskList(taskList);
            WorkFlowScreenConfigBean screenConfig = configBean.getScreenConfig();
            if (screenConfig == null) {
                continue;
            }
            String detailColumnStr = screenConfig.getDetailColumn();
            List<WorkFlowScreenConfigBean.DetailColumn> detailColumns = JSONObject.parseArray(detailColumnStr, WorkFlowScreenConfigBean.DetailColumn.class);
            List<String> videoKeys = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(detailColumns)) {
                detailColumns.forEach(column -> {
                    List<WorkFlowScreenConfigBean.SelectArr> selectArr = column.getSelectArr();
                    if (!CollectionUtils.isEmpty(selectArr)) {
                        selectArr.forEach(select -> {
                            if (Constant.VIDEO_SURVEILLANCE.equals(select.getType())) {
                                videoKeys.add(select.getKey());
                            }
                        });
                    }
                });
            }
            for (WorkFlowTask each : taskList) {
                boolean hasVideo = false;
                WorkFlowTaskSimpleView simpleTask = new WorkFlowTaskSimpleView();
                JSONObject jsonObject = JSONObject.parseObject(each.getFormData());
                String location = jsonObject.getString(configBean.getComponentKeyName());
                if (!CollectionUtils.isEmpty(videoKeys)) {
                    for (String videoKey : videoKeys) {
                        String videoObjStr = jsonObject.getString(videoKey);
                        if (StringUtils.isNotBlank(jsonObject.getString(videoKey))) {
                            JSONObject videoObj = JSONObject.parseObject(videoObjStr);
                            if (videoObj != null && StringUtils.isNotBlank(videoObj.getString(Constant.FROM_DATA_ID_KEY))) {
                                hasVideo = true;
                            }
                        }
                    }
                }
                simpleTask.setCode(each.getCode());
                simpleTask.setId(each.getId());
                simpleTask.setLocation(location);
                simpleTask.setProcessId(each.getProcessId());
                simpleTask.setHasVideo(hasVideo);
                simpleTaskList.add(simpleTask);
            }
            configBean.setBizTypeName(r.getBizTypeName());
            resultList.add(configBean);
        }
        WorkFlowScreenDto workFlowScreenDto = new WorkFlowScreenDto();
        if (!CollectionUtils.isEmpty(simpleTaskList)) {
            HashMap<Long, WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean>> map = new HashMap<>();
            resultList.forEach(each -> map.put(each.getProcessId(), each));
            workFlowScreenDto.setMap(map);
            workFlowScreenDto.setLength(simpleTaskList.size());
            workFlowScreenDto.setSimpleTaskList(simpleTaskList);
        }
        return ResultBean.success(workFlowScreenDto);
    }

    @Override
    public void removeData(List<WorkFlowTaskSearchFieldBean> fieldList, Iterator<WorkFlowTask> iterator, String formData) {
        if (formData != null) {
            JSONObject jsonObject = JSONObject.parseObject(formData);
            for (WorkFlowTaskSearchFieldBean fieldBean : fieldList) {
                String key = fieldBean.getKey();
                String value = fieldBean.getValue();
                if ("all".equals(key)) {
                    if (!formData.contains(value)) {
                        iterator.remove();
                        break;
                    }
                } else if (!org.springframework.util.StringUtils.isEmpty(value)) {
                    Object object = jsonObject.get(key);
                    if (object == null || !object.toString().contains(value)) {
                        iterator.remove();
                        break;
                    }
                }
            }
        }
    }

    @Override
    public ResultBean printTemplateSave(WorkFlowPrintTemplateBean bean) {
        Long processId = bean.getProcessId();
        String printTemplate = bean.getPrintTemplate();
        WorkFlowProcess process = workFlowProcessDao.findById(processId).orElseThrow(() -> new IllegalArgumentException("此流程不存在"));
        process.setPrintTemplate(printTemplate);
        workFlowProcessDao.save(process);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public ResultBean printTemplateGet(Long processId) {
        WorkFlowProcess process = workFlowProcessDao.findById(processId).orElseThrow(() -> new IllegalArgumentException("此流程不存在"));
        return ResultBean.success(process.getPrintTemplate());
    }

    @Override
    public ResultBean screenTypeSave(WorkFlowScreenTypeBean bean) {
        Long id = bean.getId();
        String typeName = bean.getTypeName();
        WorkFlowScreenType type;
        int count = screenTypeDao.countByTypeName(typeName);
        if (id == null) {
            if (count > 0) {
                return ResultBean.fail(101, "此名称已存在");
            }
            type = new WorkFlowScreenType();
            BeanUtils.copyProperties(bean, type);
            if (StringUtil.notEmpty(bean.getUrl())) {
                type.setCode(bizCodeGeneratorFacade.zidignyizhuanlan());
            } else {
                type.setCode(bizCodeGeneratorFacade.keshihuazhuanlan());
            }

        } else {
            type = screenTypeDao.findById(id).orElseThrow(() -> new IllegalArgumentException("此类型不存在"));
            if (!typeName.equals(type.getTypeName())) {
                if (count > 0) {
                    return ResultBean.fail(101, "此名称已存在");
                }
            }
            BeanUtils.copyProperties(bean, type);
        }
        WorkFlowScreenType save = screenTypeDao.save(type);
        //专栏保存成功 将
        return ResultBean.success(save);
    }

    @Override
    public ResultBean screenTypePage(Pageable pageable) {
        pageable = PageDataUtils.addOrderByAsc(pageable, "showNumber");
        Page<WorkFlowScreenType> page = screenTypeDao.findAll(pageable);
        Page<WorkFlowScreenTypeBean> p = PageDataUtils.convertPageData(page, (type) -> {
            WorkFlowScreenTypeBean bean = new WorkFlowScreenTypeBean();
            BeanUtils.copyProperties(type, bean);
            if (type.getColumnType() != null) {
                if (type.getColumnType().intValue() == 0) {
                    bean.setColumnTypeName("系统专栏");
                } else if (type.getColumnType().intValue() == 1) {
                    bean.setColumnTypeName("自定义专栏");
                } else if (type.getColumnType().intValue() == 2) {
                    bean.setColumnTypeName("自定义超链接专栏");
                }
            }
            if (type.getIsShow() != null) {
                if (type.getIsShow().intValue() == 0) {
                    bean.setIsShowName("隐藏");
                } else if (type.getIsShow().intValue() == 1) {
                    bean.setIsShowName("显示");
                }
            }
            return bean;
        });
        return ResultBean.pageData(p.getContent(), page.getTotalElements());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public ResultBean screenTypeDelete(Long id) {
        Assert.notNull(id, "id cannot be null");
        WorkFlowScreenType type = screenTypeDao.findById(id).orElseThrow(() -> new IllegalArgumentException("该专栏不存在"));
        //查到 该专栏下的大屏配置 将typeId设为null
        List<WorkFlowScreenConfig> configs = screenConfigDao.findByTypeId(type.getId());
        for (WorkFlowScreenConfig config : configs) {
            config.setTypeId(null);
            screenConfigDao.save(config);
        }
//        screenTypeDao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
//        //获取所有启用位置服务的流程
//        List<WorkFlowProcess> processList = workFlowProcessDao.findByLocationServiceOpen(true);
//        for (WorkFlowProcess process : processList) {
//            WorkFlowLocationConfigBean<WorkFlowScreenConfigBean, WorkFlowRailAlarmConfigBean> configBean =
//                    getLocationConfigByProcessId(process.getId(), null);
//            if (configBean != null) {
//                WorkFlowScreenConfigBean screenConfig = configBean.getScreenConfig();
//                if (screenConfig != null) {
//                    Long typeId = screenConfig.getTypeId();
//                    if (id.equals(typeId)) {
//                        return ResultDto.fail(101, "请先解除此类型与大屏专栏的绑定再删除");
//                    }
//                }
//            }
//        }
        screenTypeDao.deleteById(id);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public List<ScreenColumnBean> allColumn() {
        //获取所有启用位置服务的流程
        List<WorkFlowProcess> processList = workFlowProcessDao.findByLocationServiceOpen(true);
        if (org.springframework.util.CollectionUtils.isEmpty(processList)) {
            return Lists.newArrayList();
        }
        List<Long> processIdList = processList.stream().map(r -> r.getId()).collect(Collectors.toList());
        List<WorkFlowLocationConfig> locationConfigList = locationConfigDao.findByProcessIdIn(processIdList);
        List<Long> processIds = locationConfigList.stream().filter(r -> r.isScreenColumnOpen())
                .map(r -> r.getProcessId()).collect(Collectors.toList());
        List<WorkFlowScreenConfig> screenConfigList = screenConfigDao.findByProcessIdIn(processIds);
        List<Long> typeIdList = screenConfigList.stream().map(r -> r.getTypeId()).distinct().collect(Collectors.toList());
        List<ScreenColumnBean> resultList = screenTypeDao.findAllById(typeIdList).stream()
                .map(r -> new ScreenColumnBean(r.getId(), r.getTypeName(), r.getCode())).collect(Collectors.toList());
        return resultList;
    }

    @Override
    public ResultBean columnList(ScreenColumnBean bean) {
        Long typeId = bean.getTypeId();
        String typeName = bean.getTypeName();
        Assert.isTrue(!(typeId == null && typeName == null), "传值错误，参数不能都为空");
        //typeId不为空的情况优先
        ScreenColumnConfig config;
        if (typeId != null) {
            config = screenColumnConfigDao.findFirstByTypeId(typeId);
            WorkFlowScreenType type = screenTypeDao.findById(typeId).orElseThrow(() -> new IllegalArgumentException("此类型不存在"));
            if (config == null) {
                config = new ScreenColumnConfig();
                ScreenColumnConfigBean screenColumnConfigBean = new ScreenColumnConfigBean(type.getTypeName());
                config.setConfigJson(JSON.toJSONString(screenColumnConfigBean.getDetail()));
                config.setTypeId(typeId);
                config = screenColumnConfigDao.save(config);
            }
        } else {
            config = screenColumnConfigDao.findFirstByTypeName(typeName);
            synchronized (typeName) {
                if (config == null) {
                    config = new ScreenColumnConfig();
                    ScreenColumnConfigBean screenColumnConfigBean = new ScreenColumnConfigBean(typeName);
                    config.setConfigJson(JSON.toJSONString(screenColumnConfigBean.getDetail()));
                    config.setTypeName(typeName);
                    config = screenColumnConfigDao.save(config);
                }
            }
        }
        ScreenColumnConfigBean resultBean = new ScreenColumnConfigBean();
        BeanUtils.copyProperties(config, resultBean);
        resultBean.setDetail(JSON.parseArray(config.getConfigJson(), ScreenColumnConfigDetailBean.class));
        return ResultBean.success(resultBean);
    }

    @Override
    public ResultBean columnSave(ScreenColumnConfigBean bean) {
        //只存在修改的情况
        Long id = bean.getId();
        Assert.notNull(id, "id cannot be null");
        List<ScreenColumnConfigDetailBean> detail = bean.getDetail();
        Assert.notNull(detail, "detail cannot be null");
        ScreenColumnConfig config = screenColumnConfigDao.findById(id).orElseThrow(() -> new IllegalArgumentException("此数据不存在"));
        BeanUtils.copyProperties(bean, config);
        config.setConfigJson(JSON.toJSONString(detail));
        screenColumnConfigDao.save(config);
        return ResultBean.defaultSuccessResult();
    }

    @Override
    public List<Map<String, Object>> findAllProcessIdAndName() {
        List<Tuple> list = workFlowProcessDao.findAllProcessIdAndName();
        List<Map<String, Object>> mapList = new ArrayList<>();
        list.forEach(each -> {
            Map<String, Object> processMap = new HashMap<>();
            processMap.put("value", each.get("value", BigInteger.class));
            processMap.put("label", each.get("label", String.class));
            mapList.add(processMap);
        });
        return mapList;
    }

}
